package cn.uncode.springcloud.starter.bus.mq.rabbit;

import java.util.Date;
import java.util.UUID;

import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.support.CorrelationData;

public class RabbitmqTemplate{
	
	private RabbitTemplate rabbitTemplate;
	private RetryCache retryCache = new RetryCache();
	
	public RabbitmqTemplate(RabbitTemplate rabbitTemplate) {
		this.rabbitTemplate = rabbitTemplate;
		retryCache.setSender(this);
	}
	
	public void send(Message message) {
		MessageWithTime messageWithTime = buildInnerMessage(message);
    	rabbitTemplate.correlationConvertAndSend(messageWithTime, new CorrelationData(messageWithTime.getId()));
	}
	
	public void send(MessageWithTime message)  {
    	rabbitTemplate.correlationConvertAndSend(message, new CorrelationData(message.getId()));
	}

	public void send(String routingKey, Message message) {
		MessageWithTime messageWithTime = buildInnerMessage(message);
    	rabbitTemplate.convertAndSend(routingKey, messageWithTime, new CorrelationData(messageWithTime.getId()));
	}

	private MessageWithTime buildInnerMessage(Object message) {
		String mesageId = UUID.randomUUID().toString();
		Date time = new Date();
		MessageWithTime messageWithTime = new MessageWithTime(mesageId, time.getTime(), message);
		retryCache.add(messageWithTime);
		return messageWithTime;
	}

	public void send(String exchange, String routingKey, Message message) {
		MessageWithTime messageWithTime = buildInnerMessage(message);
    	rabbitTemplate.convertAndSend(exchange, routingKey, messageWithTime, new CorrelationData(messageWithTime.getId()));
	}

	public void convertAndSend(Object message) {
		MessageWithTime messageWithTime = buildInnerMessage(message);
    	rabbitTemplate.correlationConvertAndSend(messageWithTime, new CorrelationData(messageWithTime.getId()));
	}

	public void convertAndSend(String routingKey, Object message) {
		MessageWithTime messageWithTime = buildInnerMessage(message);
    	rabbitTemplate.convertAndSend(routingKey, messageWithTime, new CorrelationData(messageWithTime.getId()));
	}

	public void convertAndSend(String exchange, String routingKey, Object message) {
		MessageWithTime messageWithTime = buildInnerMessage(message);
    	rabbitTemplate.convertAndSend(exchange, routingKey, messageWithTime, new CorrelationData(messageWithTime.getId()));
	}

	public void convertAndSend(Object message, MessagePostProcessor messagePostProcessor) {
		MessageWithTime messageWithTime = buildInnerMessage(message);
    	rabbitTemplate.convertAndSend(messageWithTime, messagePostProcessor, new CorrelationData(messageWithTime.getId()));
	}

	public void convertAndSend(String routingKey, Object message, MessagePostProcessor messagePostProcessor)
			throws AmqpException {
		MessageWithTime messageWithTime = buildInnerMessage(message);
    	rabbitTemplate.convertAndSend(routingKey, messageWithTime, messagePostProcessor, new CorrelationData(messageWithTime.getId()));
	}

	public void convertAndSend(String exchange, String routingKey, Object message,
			MessagePostProcessor messagePostProcessor) {
		MessageWithTime messageWithTime = buildInnerMessage(message);
    	rabbitTemplate.convertAndSend(exchange, routingKey, messageWithTime, messagePostProcessor, new CorrelationData(messageWithTime.getId()));
	}

//	@Override
//	public Message receive() {
//		return null;
//	}
//
//	@Override
//	public Message receive(String queueName) {
//		return null;
//	}
//
//	@Override
//	public Message receive(long timeoutMillis) {
//		return null;
//	}
//
//	@Override
//	public Message receive(String queueName, long timeoutMillis) {
//		return null;
//	}
//
//	@Override
//	public Object receiveAndConvert() {
//		return null;
//	}
//
//	@Override
//	public Object receiveAndConvert(String queueName) {
//		return null;
//	}
//
//	@Override
//	public Object receiveAndConvert(long timeoutMillis) {
//		return null;
//	}
//
//	@Override
//	public Object receiveAndConvert(String queueName, long timeoutMillis) {
//		return null;
//	}
//
//	@Override
//	public <T> T receiveAndConvert(ParameterizedTypeReference<T> type) {
//		return null;
//	}
//
//	@Override
//	public <T> T receiveAndConvert(String queueName, ParameterizedTypeReference<T> type) {
//		return null;
//	}
//
//	@Override
//	public <T> T receiveAndConvert(long timeoutMillis, ParameterizedTypeReference<T> type) {
//		return null;
//	}
//
//	@Override
//	public <T> T receiveAndConvert(String queueName, long timeoutMillis, ParameterizedTypeReference<T> type)
//			throws AmqpException {
//		return null;
//	}
//
//	@Override
//	public <R, S> boolean receiveAndReply(ReceiveAndReplyCallback<R, S> callback) {
//		return false;
//	}
//
//	@Override
//	public <R, S> boolean receiveAndReply(String queueName, ReceiveAndReplyCallback<R, S> callback)
//			throws AmqpException {
//		return false;
//	}
//
//	@Override
//	public <R, S> boolean receiveAndReply(ReceiveAndReplyCallback<R, S> callback, String replyExchange,
//			String replyRoutingKey) {
//		return false;
//	}
//
//	@Override
//	public <R, S> boolean receiveAndReply(String queueName, ReceiveAndReplyCallback<R, S> callback,
//			String replyExchange, String replyRoutingKey) {
//		return false;
//	}
//
//	@Override
//	public <R, S> boolean receiveAndReply(ReceiveAndReplyCallback<R, S> callback,
//			ReplyToAddressCallback<S> replyToAddressCallback) {
//		return false;
//	}
//
//	@Override
//	public <R, S> boolean receiveAndReply(String queueName, ReceiveAndReplyCallback<R, S> callback,
//			ReplyToAddressCallback<S> replyToAddressCallback) {
//		return false;
//	}
//
//	@Override
//	public Message sendAndReceive(Message message) {
//		return null;
//	}
//
//	@Override
//	public Message sendAndReceive(String routingKey, Message message) {
//		return null;
//	}
//
//	@Override
//	public Message sendAndReceive(String exchange, String routingKey, Message message) {
//		return null;
//	}
//
//	@Override
//	public Object convertSendAndReceive(Object message) {
//		return null;
//	}
//
//	@Override
//	public Object convertSendAndReceive(String routingKey, Object message) {
//		return null;
//	}
//
//	@Override
//	public Object convertSendAndReceive(String exchange, String routingKey, Object message) {
//		return null;
//	}
//
//	@Override
//	public Object convertSendAndReceive(Object message, MessagePostProcessor messagePostProcessor)
//			throws AmqpException {
//		return null;
//	}
//
//	@Override
//	public Object convertSendAndReceive(String routingKey, Object message, MessagePostProcessor messagePostProcessor)
//			throws AmqpException {
//		return null;
//	}
//
//	@Override
//	public Object convertSendAndReceive(String exchange, String routingKey, Object message,
//			MessagePostProcessor messagePostProcessor) {
//		return null;
//	}
//
//	@Override
//	public <T> T convertSendAndReceiveAsType(Object message, ParameterizedTypeReference<T> responseType)
//			throws AmqpException {
//		return null;
//	}
//
//	@Override
//	public <T> T convertSendAndReceiveAsType(String routingKey, Object message,
//			ParameterizedTypeReference<T> responseType) {
//		return null;
//	}
//
//	@Override
//	public <T> T convertSendAndReceiveAsType(String exchange, String routingKey, Object message,
//			ParameterizedTypeReference<T> responseType) {
//		return null;
//	}
//
//	@Override
//	public <T> T convertSendAndReceiveAsType(Object message, MessagePostProcessor messagePostProcessor,
//			ParameterizedTypeReference<T> responseType) {
//		return null;
//	}
//
//	@Override
//	public <T> T convertSendAndReceiveAsType(String routingKey, Object message,
//			MessagePostProcessor messagePostProcessor, ParameterizedTypeReference<T> responseType)
//			throws AmqpException {
//		return null;
//	}
//
//	@Override
//	public <T> T convertSendAndReceiveAsType(String exchange, String routingKey, Object message,
//			MessagePostProcessor messagePostProcessor, ParameterizedTypeReference<T> responseType)
//			throws AmqpException {
//		return null;
//	}
	

}
